import base64
import pickle

from django.shortcuts import render
from django.views import View
import json
from django import http
from django_redis import get_redis_connection


from goods.models import SKU
from utils.response_code import RETCODE


# Create your views here.
class CartSelectAllView(View):
    def put(self, request):
        json_dict = json.loads(request.body.decode())
        selected = json_dict.get('selected', True)

        if selected and not isinstance(selected, bool):
            return http.HttpResponseForbidden('Parameter(selected) format was wrong')

        user = request.user
        if user.is_authenticated:
            redis_conn = get_redis_connection('carts')
            pl = redis_conn.pipeline()
            # redis_carts_skus = pl.hgetall('carts_%s' % user.id)
            redis_carts_skus = redis_conn.hgetall('carts_%s' % user.id)
            redis_skus = redis_carts_skus.keys()

            if selected:
                pl.sadd('selected_%s' % user.id, *redis_skus)
            else:
                pl.srem('selected_%s' % user.id, *redis_skus)

            pl.execute()

            return http.JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK'})

        else:
            cookie_carts = request.COOKIES.get('carts')
            response = http.JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK'})

            if cookie_carts:
                cookie_carts_bytes = cookie_carts.encode()
                cookie_carts_base64 = base64.b64decode(cookie_carts_bytes)
                cookie_dict = pickle.loads(cookie_carts_base64)

                for sku_id in cookie_dict.keys():
                    cookie_dict[sku_id]['selected'] = selected

                cookie_dict_pk = pickle.dumps(cookie_dict)
                cookie_dict_base64 = base64.b64encode(cookie_dict_pk)
                cookie_dict_str = cookie_dict_base64.decode()

                response.set_cookie('carts', cookie_dict_str)

            return response


class CartsView(View):
    def post(self, request):
        json_dict = json.loads(request.body.decode())
        sku_id = json_dict.get('sku_id')
        count = json_dict.get('count')
        selected = json_dict.get('selected', True)

        if not all([sku_id, count]):
            return http.HttpResponseForbidden('Missing required parameters')

        try:
            SKU.objects.get(id=sku_id)
        except SKU.DoesNotExist:
            return http.HttpResponseForbidden('SKU id was wrong')

        try:
            count = int(count)
        except Exception as e:
            return http.HttpResponseForbidden('Parameter(count) format was wrong')

        if selected and not isinstance(selected, bool):
            return http.HttpResponseForbidden('Parameter(selected) format was wrong')

        user = request.user
        if user.is_authenticated:
            redis_conn = get_redis_connection('carts')
            pl = redis_conn.pipeline()
            pl.hincrby('carts_%s' % user.id, sku_id, count)

            if selected:
                pl.sadd('selected_%s' % user.id, sku_id)

            pl.execute()

            return http.JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK'})

        else:
            cookie_carts = request.COOKIES.get('carts')

            if cookie_carts:
                cookie_carts_bytes = cookie_carts.encode()
                cookie_carts_base64 = base64.b64decode(cookie_carts_bytes)
                cookie_dict = pickle.loads(cookie_carts_base64)
            else:
                cookie_dict = {}

            if sku_id in cookie_dict:
                origin_count = cookie_dict[sku_id].get('count')
                count += origin_count

            cookie_dict[sku_id] = {
                'count': count,
                'selected': selected
            }

            cookie_dict_pk = pickle.dumps(cookie_dict)
            cookie_dict_base64 = base64.b64encode(cookie_dict_pk)
            cookie_dict_str = cookie_dict_base64.decode()

            response = http.JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK'})
            response.set_cookie('carts', cookie_dict_str)
            return response

    def get(self, request):
        user = request.user
        if user.is_authenticated:
            redis_conn = get_redis_connection('carts')
            redis_cart = redis_conn.hgetall('carts_%s' % user.id)
            redis_selected = redis_conn.smembers('selected_%s' % user.id)

            cart_dict = {}
            for sku_id, count in redis_cart.items():
                cart_dict[int(sku_id)] = {
                    'count': int(count),
                    'selected': sku_id in redis_selected
                }

        else:
            cookie_carts = request.COOKIES.get('carts')

            if cookie_carts:
                cookie_carts_bytes = cookie_carts.encode()
                cookie_carts_base64 = base64.b64decode(cookie_carts_bytes)
                cart_dict = pickle.loads(cookie_carts_base64)
            else:
                cart_dict = {}

        sku_ids = cart_dict.keys()
        skus = SKU.objects.filter(id__in=sku_ids)

        cart_list = []
        for sku in skus:
            cart_list.append({
                'id': sku.id,
                'name': sku.name,
                'price': str(sku.price),
                'default_image_url': sku.default_image.url,
                'count': cart_dict[sku.id].get('count'),
                'selected': str(cart_dict[sku.id].get('selected')),
                'amount': str(sku.price * cart_dict[sku.id].get('count'))
                })

        context = {
            'cart_list': cart_list
        }

        return render(request, 'cart.html', context)

    def put(self, request):
        json_dict = json.loads(request.body.decode())
        sku_id = json_dict.get('sku_id')
        count = json_dict.get('count')
        selected = json_dict.get('selected', True)

        if not all([sku_id, count]):
            return http.HttpResponseForbidden('Missing required parameters')

        try:
            sku = SKU.objects.get(id=sku_id)
        except SKU.DoesNotExist:
            return http.HttpResponseForbidden('SKU id was wrong')

        try:
            count = int(count)
        except Exception as e:
            return http.HttpResponseForbidden('Parameter(count) format was wrong')

        if selected and not isinstance(selected, bool):
            return http.HttpResponseForbidden('Parameter(selected) format was wrong')

        user = request.user
        if user.is_authenticated:
            redis_conn = get_redis_connection('carts')
            pl = redis_conn.pipeline()
            pl.hset('carts_%s' % user.id, sku_id, count)

            if selected:
                pl.sadd('selected_%s' % user.id, sku_id)
            else:
                pl.srem('selected_%s' % user.id, sku_id)

            pl.execute()

            cart_sku = {
                'id': sku.id,
                'name': sku.name,
                'price': str(sku.price),
                'default_image_url': sku.default_image.url,
                'count': count,
                'selected': selected,
                'amount': str(sku.price * count)
            }
            return http.JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK', 'cart_sku': cart_sku})

        else:
            cookie_carts = request.COOKIES.get('carts')

            if cookie_carts:
                cookie_carts_bytes = cookie_carts.encode()
                cookie_carts_base64 = base64.b64decode(cookie_carts_bytes)
                cookie_dict = pickle.loads(cookie_carts_base64)
            else:
                cookie_dict = {}

            cookie_dict[sku_id] = {
                'count': count,
                'selected': selected
            }

            cookie_dict_pk = pickle.dumps(cookie_dict)
            cookie_dict_base64 = base64.b64encode(cookie_dict_pk)
            cookie_dict_str = cookie_dict_base64.decode()

            cart_sku = {
                'id': sku.id,
                'name': sku.name,
                'price': str(sku.price),
                'default_image_url': sku.default_image.url,
                'count': count,
                'selected': selected,
                'amount': str(sku.price * count)
            }

            response = http.JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK', 'cart_sku': cart_sku})
            response.set_cookie('carts', cookie_dict_str)
            return response

    def delete(self, request):
        json_dict = json.loads(request.body.decode())
        sku_id = json_dict.get('sku_id')

        if not all([sku_id]):
            return http.HttpResponseForbidden('Missing required parameters')

        try:
            SKU.objects.get(id=sku_id)
        except SKU.DoesNotExist:
            return http.HttpResponseForbidden('SKU id was wrong')

        user = request.user
        if user.is_authenticated:
            redis_conn = get_redis_connection('carts')
            pl = redis_conn.pipeline()
            pl.hdel('carts_%s' % user.id, sku_id)
            pl.srem('selected_%s' % user.id, sku_id)
            pl.execute()

            return http.JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK'})

        else:
            cookie_carts = request.COOKIES.get('carts')

            if cookie_carts:
                cookie_carts_bytes = cookie_carts.encode()
                cookie_carts_base64 = base64.b64decode(cookie_carts_bytes)
                cookie_dict = pickle.loads(cookie_carts_base64)
            else:
                cookie_dict = {}

            response = http.JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK'})

            if sku_id in cookie_dict:
                del cookie_dict[sku_id]

                cookie_dict_pk = pickle.dumps(cookie_dict)
                cookie_dict_base64 = base64.b64encode(cookie_dict_pk)
                cookie_dict_str = cookie_dict_base64.decode()
                response.set_cookie('carts', cookie_dict_str)

            return response
